package com.note;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ikang.idata.common.entity.EleOverallTrendFilm;
import com.ikang.idata.common.entity.vo.EleOverallTrendResult;
import com.ikang.idata.common.enums.ElectricityBoardEnum;
import com.ikang.idata.search.search.util.HttpClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import static java.util.stream.Collectors.*;

/**
 * @author: hao.liu
 * @Date: 2021/8/8 09:40
 */
@Service
@Slf4j
public class EleOverallTrendKanbanService {

    @Value("${bigdata.url.electricityboard.electricityboardUrl}")
    private String electricityboardUrl;

    private static final Integer SEARCH_SIZEMAX = 30000;

    /**
     * @Description: 第一个时间  当前时间得值
     */
    public EleOverallTrendResult getTime (List<String> channelCodes, String purchaseDateStart, String purchaseDateEnd) {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder queryBuilder = getQueryBuilder(channelCodes, purchaseDateStart, purchaseDateEnd);
        builder.size(SEARCH_SIZEMAX);
        builder.query(queryBuilder);
        // 调用接口
        return this.invokeAndGetResult(builder.toString());
    }

    public BoolQueryBuilder getQueryBuilder(List<String> purchaseChannelCode, String start, String end) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        List<QueryBuilder> must = queryBuilder.must();
        // 渠道
        must.add(QueryBuilders.termsQuery(ElectricityBoardEnum.PURCHASECHANNELCODE.getFields(), purchaseChannelCode));
        // 起止时间
        must.add(QueryBuilders.rangeQuery(ElectricityBoardEnum.PURCHASEDATE.getFields())
                .gte(start)
                .lte(end)
                .includeLower(true)
                .includeUpper(true));
        return queryBuilder;
    }

    public EleOverallTrendResult invokeAndGetResult(String queryDsl) {
        log.info("EleOverallTrendFilm transaction queryDsl:{}", queryDsl);
        JSONObject jsonObject = HttpClient.esRequest(electricityboardUrl, queryDsl);
        // 结果解析
        JSONArray hits = jsonObject.getJSONArray("hits");
        EleOverallTrendResult resultList = this.parseResult(hits);
        return resultList;
    }

    public EleOverallTrendResult parseResult(JSONArray hits) {
        //11个小框的值
        List<EleOverallTrendFilm> result = new ArrayList<>();
        if (null != hits && hits.size() > 0) {
            for (Object hit : hits) {
                EleOverallTrendFilm eleOverallTrendFilm = setData(hit);
                result.add(eleOverallTrendFilm);
            }
        }

        // 数据指标  按月分组展示
        // 累计销售额 11个 月份  数值
        Map<String, BigDecimal> saleAmountcsMap = result.stream()
                .filter(item -> null != item.getSaleAmount())
                .map(res -> {
                    if (StringUtils.isNotBlank(res.getPurchaseDate())) {
                        res.setMonth(getMonth(res.getPurchaseDate()));
                    }
                    return res;
                }).sorted(Comparator.comparing(EleOverallTrendFilm::getPurchaseDate))
                .collect(groupingBy(EleOverallTrendFilm::getMonth, LinkedHashMap::new, mapping(EleOverallTrendFilm::getSaleAmount, reducing(BigDecimal.ZERO, (bigDecimal, bigDecimal2) -> bigDecimal.add(bigDecimal2).setScale(2, RoundingMode.HALF_UP)))));

        //累计销售额 对用的值
        Map<String, Object> saleAmountMap = new HashMap<>(8);
        saleAmountMap.put("累计销售额", saleAmountcsMap);
        saleAmountMap.put("unit", "元");

        //2 放月份对应的数据
        Map<String, BigDecimal> incomecsMap = result.stream()
                .filter(item -> null != item.getIncomeAmount())
                .map(res -> {
                    if (StringUtils.isNotBlank(res.getPurchaseDate())) {
                        res.setMonth(getMonth(res.getPurchaseDate()));
                    }
                    return res;
                }).sorted(Comparator.comparing(EleOverallTrendFilm::getPurchaseDate))
                .collect(groupingBy(EleOverallTrendFilm::getMonth, LinkedHashMap::new, mapping(EleOverallTrendFilm::getIncomeAmount, reducing(BigDecimal.ZERO, (bigDecimal, bigDecimal2) -> bigDecimal.add(bigDecimal2).setScale(2, RoundingMode.HALF_UP)))));
        //放名称加数据
        Map<String, Object> incomeAmountMap = new HashMap<>(8);
        incomeAmountMap.put("累计收入", incomecsMap);
        incomeAmountMap.put("unit", "元");

        //3 累计退款
        Map<String, BigDecimal> cancelComecsMap = result.stream()
                .filter(item -> null != item.getCancelCome())
                .map(res -> {
                    if (StringUtils.isNotBlank(res.getPurchaseDate())) {
                        res.setMonth(getMonth(res.getPurchaseDate()));
                    }
                    return res;
                }).sorted(Comparator.comparing(EleOverallTrendFilm::getPurchaseDate))
                .collect(groupingBy(EleOverallTrendFilm::getMonth, LinkedHashMap::new, mapping(EleOverallTrendFilm::getCancelCome, reducing(BigDecimal.ZERO, (bigDecimal, bigDecimal2) -> bigDecimal.add(bigDecimal2).setScale(2, RoundingMode.HALF_UP)))));

        Map<String, Object> cancelComeMap = new HashMap<>(8);
        cancelComeMap.put("累计退款", cancelComecsMap);
        cancelComeMap.put("unit", "元");

        //4
        Map<String, BigDecimal> saleNumcsMap = result.stream()
                .filter(item -> null != item.getSaleNum())
                .map(res -> {
                    if (StringUtils.isNotBlank(res.getPurchaseDate())) {
                        res.setMonth(getMonth(res.getPurchaseDate()));
                    }
                    return res;
                }).sorted(Comparator.comparing(EleOverallTrendFilm::getPurchaseDate))
                .collect(groupingBy(EleOverallTrendFilm::getMonth, LinkedHashMap::new, mapping(EleOverallTrendFilm::getSaleNum, reducing(BigDecimal.ZERO, (bigDecimal, bigDecimal2) -> bigDecimal.add(bigDecimal2).setScale(2, RoundingMode.HALF_UP)))));

        Map<String, Object> saleNumMap = new HashMap<>(8);
        saleNumMap.put("累计售出商品", saleNumcsMap);
        saleNumMap.put("unit", "件");

        //6 累计购买订单
        Map<String, BigDecimal> salePhonecsMap = result.stream()
                .filter(item -> null != item.getSalePhone())
                .map(res -> {
                    if (StringUtils.isNotBlank(res.getPurchaseDate())) {
                        res.setMonth(getMonth(res.getPurchaseDate()));
                    }
                    return res;
                }).sorted(Comparator.comparing(EleOverallTrendFilm::getPurchaseDate))
                .collect(groupingBy(EleOverallTrendFilm::getMonth, LinkedHashMap::new, mapping(EleOverallTrendFilm::getSalePhone, reducing(BigDecimal.ZERO, (bigDecimal, bigDecimal2) -> bigDecimal.add(bigDecimal2).setScale(2, RoundingMode.HALF_UP)))));

        Map<String, Object> salePhoneMap = new HashMap<>(8);
        salePhoneMap.put("累计购买订单", salePhonecsMap);
        salePhoneMap.put("unit", "个");


        //9 预约人数
        Map<String, BigDecimal> regNumcsMap = result.stream()
                .filter(item -> null != item.getRegNum())
                .map(res -> {
                    if (StringUtils.isNotBlank(res.getPurchaseDate())) {
                        res.setMonth(getMonth(res.getPurchaseDate()));
                    }
                    return res;
                }).sorted(Comparator.comparing(EleOverallTrendFilm::getPurchaseDate))
                .collect(groupingBy(EleOverallTrendFilm::getMonth, LinkedHashMap::new, mapping(EleOverallTrendFilm::getRegNum, reducing(BigDecimal.ZERO, (bigDecimal, bigDecimal2) -> bigDecimal.add(bigDecimal2).setScale(2, RoundingMode.HALF_UP)))));

        Map<String, Object> regNumMap = new HashMap<>(8);
        regNumMap.put("预约人数", regNumcsMap);
        regNumMap.put("unit", "人");

        //10  到检人数
        Map<String, BigDecimal> checkNumcsMap = result.stream()
                .filter(item -> null != item.getCheckNum())
                .map(res -> {
                    if (StringUtils.isNotBlank(res.getPurchaseDate())) {
                        res.setMonth(getMonth(res.getPurchaseDate()));
                    }
                    return res;
                }).sorted(Comparator.comparing(EleOverallTrendFilm::getPurchaseDate))
                .collect(groupingBy(EleOverallTrendFilm::getMonth, LinkedHashMap::new, mapping(EleOverallTrendFilm::getCheckNum, reducing(BigDecimal.ZERO, (bigDecimal, bigDecimal2) -> bigDecimal.add(bigDecimal2).setScale(2, RoundingMode.HALF_UP)))));

        Map<String, Object> checkNumMap = new HashMap<>(8);
        checkNumMap.put("到检人数", checkNumcsMap);
        checkNumMap.put("unit", "人");

        //11 出报告人数
        Map<String, BigDecimal> reportNumcsMap = result.stream()
                .filter(item -> null != item.getReportNum())
                .map(res -> {
                    if (StringUtils.isNotBlank(res.getPurchaseDate())) {
                        res.setMonth(getMonth(res.getPurchaseDate()));
                    }
                    return res;
                }).sorted(Comparator.comparing(EleOverallTrendFilm::getPurchaseDate))
                .collect(groupingBy(EleOverallTrendFilm::getMonth, LinkedHashMap::new, mapping(EleOverallTrendFilm::getReportNum, reducing(BigDecimal.ZERO, (bigDecimal, bigDecimal2) -> bigDecimal.add(bigDecimal2).setScale(2, RoundingMode.HALF_UP)))));
        Map<String, Object> reportNumMap = new HashMap<>(8);
        reportNumMap.put("出报告人数", reportNumcsMap);
        reportNumMap.put("unit", "人");

        //大的11个字段  对应的值 汇总添加
        List<Map<String,Object>> allList = new ArrayList<>();
        allList.add(saleAmountMap);
        allList.add(incomeAmountMap);
        allList.add(cancelComeMap);
        allList.add(saleNumMap);
        allList.add(salePhoneMap);
        allList.add(regNumMap);
        allList.add(checkNumMap);
        allList.add(reportNumMap);

        EleOverallTrendResult eleOverallTrendResult = new EleOverallTrendResult();
        //11
        eleOverallTrendResult.setList(result);
        //柱状图
        eleOverallTrendResult.setAllList(allList);
        return eleOverallTrendResult;
    }

    public EleOverallTrendFilm setData(Object hit) {
        Map<String, Map<String, Object>> map = (Map) hit;
        Map<String, Object> source = map.get("_source");
        EleOverallTrendFilm eleOverallTrendFilm = new EleOverallTrendFilm();
        Object purchaseChannelCode = source.get("purchase_channel_code");
        Object purchaseDate = source.get("purchase_date");
        Object saleAmount = source.get("sale_amount");
        Object incomeAmount = source.get("income_amount");
        Object cancelAmount = source.get("cancel_amount");
        Object saleNum = source.get("sale_num");
        Object saleCardPrice = source.get("sale_card_price");
        Object salePhone = source.get("sale_phone");
        Object personalNum = source.get("personal_num");
        Object salePhonePrice = source.get("sale_phone_price");
        Object regNum = source.get("reg_num");
        Object checkNum = source.get("check_num");
        Object reportNum = source.get("report_num");
        //类型不一样
        if (null != purchaseChannelCode) {
            eleOverallTrendFilm.setPurchaseChannelCode(purchaseChannelCode.toString());
        }
        if (null != purchaseDate) {
            eleOverallTrendFilm.setPurchaseDate(purchaseDate.toString());
        }
        if (null != saleAmount) {
            eleOverallTrendFilm.setSaleAmount(new BigDecimal(saleAmount.toString()));
        }
        if (null != incomeAmount) {
            eleOverallTrendFilm.setIncomeAmount(new BigDecimal(incomeAmount.toString()));
        }
        if (null != cancelAmount) {
            eleOverallTrendFilm.setCancelCome(new BigDecimal(cancelAmount.toString()));
        }
        if (null != saleNum) {
            eleOverallTrendFilm.setSaleNum(new BigDecimal(saleNum.toString()));
        }
        if (null != saleCardPrice) {
            eleOverallTrendFilm.setSaleCardPrice(new BigDecimal(saleCardPrice.toString()));
        }
        if (null != salePhone) {
            eleOverallTrendFilm.setSalePhone(new BigDecimal(salePhone.toString()));
        }
        if (null != personalNum) {
            eleOverallTrendFilm.setPersonalNum(new BigDecimal(personalNum.toString()));
        }
        if (null != salePhonePrice) {
            eleOverallTrendFilm.setSalePhonePrice(new BigDecimal(salePhonePrice.toString()));
        }
        if (null != regNum) {
            eleOverallTrendFilm.setRegNum(new BigDecimal(regNum.toString()));
        }
        if (null != checkNum) {
            eleOverallTrendFilm.setCheckNum(new BigDecimal(checkNum.toString()));
        }
        if (null != reportNum) {
            eleOverallTrendFilm.setReportNum(new BigDecimal(reportNum.toString()));
        }
        return eleOverallTrendFilm;
    }


    public String getMonth(String date) {
        //格式化为年月
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar min = Calendar.getInstance();
        try {
            min.setTime(sdf.parse(date));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);
        return sdf.format(min.getTime());
    }

}
